#include "Strategy.h"
#include <fstream>
using namespace std;
struct BUF
{
	long nano;
	double mid;
	int Volume;
	int dvol;
	double var1;
	double var2;
	double thres;
};

double cal_mid(double bid, double ask)
{
	if(bid > 0 && ask > 0)
		return (bid+ask)*0.5;
	else if(bid > 0)
		return bid;
	else
		return ask;
}
class A1 : public Strategy 
{
private:
	long window_;
	long interval_;
	BUF** buffer_;
	long* tail_;
public:
	void on_init(const nlohmann::json config)
	{
		window_ = config["window"].get<int>();
		interval_ = config["interval"].get<int>();
		int nsymbol = get_nsymbol();
		buffer_ = new BUF*[nsymbol];	
		tail_ = new long[nsymbol];	
		string name;
		for(int i = 0; i < nsymbol; i++)
		{
			buffer_[i] = new BUF[window_+1];
			tail_[i] = 0;
		}
		
	}

	void on_process(const Ticker* t)
	{
		const Snapshot* data = &t->last;
		BUF* lst = buffer_[t->idx] + tail_[t->idx] % (window_+1);
		if(data->nano <= lst->nano)
			return;
		tail_[t->idx] += 1;
		BUF* cur = buffer_[t->idx] + tail_[t->idx] % (window_+1);
		double mid = cal_mid(data->BidPrice1 * 1e-3, data->AskPrice1 * 1e-3);
		int dvol = lst->Volume ==0 ? 0 : (data->Volume >= lst->Volume ? (data->Volume - lst->Volume) : data->Volume);
		cur->nano = data->nano;
		cur->Volume = data->Volume;
		cur->dvol = dvol;
		cur->mid  = mid;
		BUF* out = buffer_[t->idx] + (tail_[t->idx] + 1) % (window_+1);
		cur->var1 = lst->var1 + dvol - out->dvol;
		cur->var2 = lst->var2 + dvol * mid - out->dvol * out->mid;
		cur->thres = cur->var2 / cur->var1;
		int target = t->position;
		long holding_time = (get_nano() - t->position_nano )/1e9;
		if(tail_[t->idx] > window_ && holding_time > interval_)
		{
			if(mid > cur->thres)
				target = 1;
			else if(mid < cur->thres)
				target = -1;
		}
		bool to_print = target!= t->position || lst->Volume > cur->Volume || is_real_time();
		if(t->position == 0 && target != 0)
		{
			send_order(target, OFFSET_OPEN, t->idx);
		}
		else if(t->position!=0 && target == 0)
		{
			send_order(-t->position, OFFSET_CLOSE, t->idx);
		}
		else if((target > 0 && t->position < 0) || (target < 0 && t->position > 0))
		{
			send_order(-t->position, OFFSET_CLOSE, t->idx);
			send_order(target, OFFSET_OPEN, t->idx);
		}
		if(to_print)
		{
			FILE* log = fopen(get_log_name(), "a+");
			fprintf(stdout, "%s %.3f %+d ht:%8ld mid:%.3f thres:%.3f\n",Timer::nano2str(get_nano()).c_str(), data->Time*0.001 ,t->position, holding_time, cur->mid,  cur->thres);
			fprintf(log, "%s %.3f %+d ht:%8ld mid:%.3f thres:%.3f\n",Timer::nano2str(get_nano()).c_str(), data->Time*0.001, t->position, holding_time, cur->mid,  cur->thres);
			fclose(log);
		}

	}
};

int main(int argc, char **argv)
{
	string config_file = "strategy.json";
	if(argc > 1)
		config_file = argv[1];
	ifstream in(config_file);
    string content((istreambuf_iterator<char>(in)), istreambuf_iterator<char>());
	in.close();
	nlohmann::json config = nlohmann::json::parse(content);
	shared_ptr<A1> a = make_shared<A1>();
	if(a->init(config))
		a->run();
	return 0;
}
